#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <unistd.h>

#define WIDTH 10
#define HEIGHT 20
#define BLOCK_TYPES 7

typedef struct {
    int dY;
    int dX;
} BlockShape;


BlockShape gBlocks[BLOCK_TYPES][4][4] = {
    // I型
    {
        {{0,0}, {0,1}, {0,2}, {0,3}},
        {{0,0}, {1,0}, {2,0}, {3,0}},
        {{0,0}, {0,1}, {0,2}, {0,3}},
        {{0,0}, {1,0}, {2,0}, {3,0}},
    },
    // O型
    {
        {{0,0}, {1,0}, {0,1}, {1,1}},
        {{0,0}, {1,0}, {0,1}, {1,1}},
        {{0,0}, {1,0}, {0,1}, {1,1}},
        {{0,0}, {1,0}, {0,1}, {1,1}}
    },
    // T型
    {
        {{1,0}, {0,1}, {1,1}, {1,2}},
        {{0,0}, {1,0}, {2,0}, {1,1}},
        {{1,0}, {0,1}, {1,1}, {1,2}},
        {{0,1}, {1,1}, {2,1}, {1,0}},
    },
    // Z型
    {
        {{0,0}, {0,1}, {1,1}, {1,2}},
        {{1,0}, {2,0}, {0,1}, {1,1}},
        {{0,0}, {0,1}, {1,1}, {1,2}},
        {{1,0}, {2,0}, {0,1}, {1,1}},
    },
    // S型
    {
        {{1,0}, {0,1}, {1,1}, {0,2}},
        {{0,0}, {1,0}, {1,1}, {2,1}},
        {{1,0}, {0,1}, {1,1}, {0,2}},
        {{0,0}, {1,0}, {1,1}, {2,1}},
    },
    // J型
    {
        {{1,0}, {1,1}, {1,2}, {0,0}},
        {{0,0}, {0,1}, {1,0}, {2,0}},
        {{0,0}, {0,1}, {0,2}, {1,2}},
        {{0,1}, {1,1}, {2,1}, {2,0}},
    },
    // L型
    {
        {{1,0}, {1,1}, {1,2}, {0,2}},
        {{0,0}, {1,0}, {2,0}, {2,1}},
        {{0,0}, {1,0}, {0,1}, {0,2}},
        {{0,0}, {0,1}, {1,1}, {2,1}}
    }
};

const double weights[] = {
    -4.5,
    3.4,
    -3.1,
    -9.3,
    -7.8,
    -3.5
};

long int gScore = 0;
int gGameBoard[HEIGHT][WIDTH] = {0};
int gTempBoard[HEIGHT][WIDTH] = {0};

int findLowestY(int x, int rotation, int type) {
    BlockShape* shape = gBlocks[type][rotation];
    int maxY = -1;
    for (int y = 0; y <= HEIGHT-6; y++) {
        int isValid = 1;
        for (int i = 0; i < 4; i++) {
            int bx = x + shape[i].dX;
            int by = y + shape[i].dY;
            if (bx < 0 || bx >= WIDTH || by < 0 || by >= HEIGHT-5 || gGameBoard[by][bx]) {
                isValid = 0;
                break;
            }
        }
        if (isValid) maxY = y;
        else break;
    }
    return maxY;
}

int eliminateLines(int board[HEIGHT][WIDTH]) {
    int lines = 0;
    for (int y = HEIGHT-6; y >= 0; y--) {
        int isFull = 1;
        for (int x = 0; x < WIDTH; x++) {
            if (!board[y][x]) {
                isFull = 0;
                break;
            }
        }
        if (isFull) {
            lines++;
            for (int yy = y; yy > 0; yy--)
                memcpy(board[yy], board[yy-1], WIDTH*sizeof(int));
            memset(board[0], 0, WIDTH*sizeof(int));
            y++;
        }
    }
    return lines;
}

int calculateScore(int lines) {
    const int points[] = {0, 100, 300, 500, 800};
    gScore += points[lines];
    return points[lines];
}

void placeBlock(int x, int y, int rotation, int type, int board[HEIGHT][WIDTH]) {
    BlockShape* shape = gBlocks[type][rotation];
    for (int i = 0; i < 4; i++) {
        int bx = x + shape[i].dX;
        int by = y + shape[i].dY;
        if (by >= 0 && by < HEIGHT-5 && bx >= 0 && bx < WIDTH)
            board[by][bx] = 1;
    }
}

int calculateWellSums(int board[HEIGHT][WIDTH]) {
    int wellSum = 0;
    for (int x = 0; x < WIDTH; x++) {
        for (int y = HEIGHT-6; y >=0; y--) {
            if (!board[y][x]) {
                int left = (x == 0) ? 1 : board[y][x-1];
                int right = (x == WIDTH-1) ? 1 : board[y][x+1];
                if (left && right) {
                    int depth = 0;
                    for (int yy = y; yy >= 0; yy--) {
                        if (!board[yy][x] && (x == 0 || board[yy][x-1]) && (x == WIDTH-1 || board[yy][x+1])) {
                            depth++;
                        } else break;
                    }
                    for (int i = depth; i >0; i--)
                        wellSum += i;
                    y -= depth - 1;
                }
            }
        }
    }
    return wellSum;
}

int calculateLandingHeight(int y, BlockShape* shape) {
    int maxY = 0;
    for (int i = 0; i < 4; i++) {
        int currentY = y + shape[i].dY;
        if (currentY > maxY) maxY = currentY;
    }
    return maxY;
}

void findBestMove(int type, int *bestRot, int *bestX) {
    double bestScore = -INFINITY;
    *bestRot = 0;
    *bestX = 0;

    for (int rot = 0; rot < 4; rot++) {
        BlockShape* shape = gBlocks[type][rot];
        int minX = 0, maxX = 0;
        for (int i = 0; i < 4; i++) {
            if (shape[i].dX < minX) minX = shape[i].dX;
            if (shape[i].dX > maxX) maxX = shape[i].dX;
        }

        int startX = -minX;
        int endX = WIDTH - maxX - 1;

        for (int x = startX; x <= endX; x++) {
            int y = findLowestY(x, rot, type);
            if (y == -1) continue;

            memcpy(gTempBoard, gGameBoard, sizeof(gGameBoard));
            placeBlock(x, y, rot, type, gTempBoard);
            int lines = eliminateLines(gTempBoard);

            double lh = HEIGHT-5 - (y + calculateLandingHeight(y, shape)) / 2.0;
            int rt = 0, ct = 0, holes = 0, wells = 0;

            for (int yy = 0; yy < HEIGHT-5; yy++) {
                int prev = 1;
                for (int xx = 0; xx < WIDTH; xx++) {
                    if (gTempBoard[yy][xx] != prev) rt++;
                    prev = gTempBoard[yy][xx];
                }
                if (prev != 1) rt++;
            }

            for (int xx = 0; xx < WIDTH; xx++) {
                int prev = 1;
                for (int yy = 0; yy < HEIGHT-5; yy++) {
                    if (gTempBoard[yy][xx] != prev) ct++;
                    prev = gTempBoard[yy][xx];
                }
                if (prev != 1) ct++;
            }

            for (int xx = 0; xx < WIDTH; xx++) {
                int blockAbove = 0;
                for (int yy = 0; yy < HEIGHT-5; yy++) {
                    if (gTempBoard[yy][xx]) blockAbove = 1;
                    else if (blockAbove) holes++;
                }
            }

            wells = calculateWellSums(gTempBoard);
            double currentScore = 
                weights[0] * lh +
                weights[1] * lines +
                weights[2] * rt +
                weights[3] * ct +
                weights[4] * holes +
                weights[5] * wells;

            if (currentScore > bestScore) {
                bestScore = currentScore;
                *bestRot = rot;
                *bestX = x;
            }
        }
    }
}

int getBlockType(char block) {
    switch (block) {
        case 'I': return 0;
        case 'O': return 1;
        case 'T': return 2;
        case 'Z': return 3;
        case 'S': return 4;
        case 'J': return 5;
        case 'L': return 6;
        default: return -1;
    }
}

void getFirst(char* s0, char* s1) {
        while (scanf("%c%c", s0, s1) != 2) continue;
}

void getInput(char* si) {
    scanf("%c", si);
}

void outPut(int x, int rot) {
    printf("%d %d\n", rot, x % 10);
    printf("%ld\n", gScore);
    fflush(stdout);
}

int main() {
    int gameOver = 0;
    int type = 0, rotation = 0, x = 0;
    char s0 = 0, s1 = 0;
    gScore = 0;
    memset(gGameBoard, 0, sizeof(gGameBoard));
    memset(gTempBoard, 0, sizeof(gTempBoard));

    getFirst(&s0, &s1);
    while (!gameOver) {
        type = getBlockType(s0);
        if (type == -1) return 0;

        findBestMove(type, &rotation, &x);
        int y = findLowestY(x, rotation, type);

        placeBlock(x, y, rotation, type, gGameBoard);
        int lines = eliminateLines(gGameBoard);
        calculateScore(lines);

        outPut(x, rotation);

        s0 = s1;
        if (s0 == 'X') return 0;
        getchar();
        getInput(&s1);
        if (s1 == 'E') return 0;
    }
    return 0;
}